package com.hanlink.dsp.protocols;


import android.text.TextUtils;

import com.hanlink.dsp.BtDspApplication;

import com.hanlink.dsp.DspSettings;
import com.hanlink.dsp.ca.model.channel.EqChannel;
import com.hanlink.dsp.ca.model.channel.LevelChannel;
import com.hanlink.dsp.ca.model.channel.SummingChannel;
import com.hanlink.dsp.ca.model.channel.XoverChannel;
import com.hanlink.dsp.util.Constants;
import com.qztech.bluetooth.ReceiveDataUtil;
import com.qztech.sdk.model.SettingConstants;
import com.qztech.sdk.utils.BLog;
import com.qztech.sdk.utils.ByteUtil;
import com.qztech.utils.YzDebug;

import java.io.File;
import java.io.FileWriter;
import java.util.Arrays;
import java.util.List;

/**
 * @author:zhanghb
 * @date:2019/3/23
 * @email:2573475062@qq.com
 **/
public class ParseDataProtocolUtil {
    private final static byte NULL = (byte) (0xff);
    private static int INDEX;
    private static int mPreCheckLength = 0;
    public static void init() {
        INDEX = 0;
        mPreCheckLength = 0;
        ReceiveDataUtil.init();
    }

    public static void readData(int index) {
        INDEX = index;
    }

    public static int getReadDataIndex() {
        return INDEX;
    }


    public static void parseAll() {
        final int dataLineLength = 40;
        StringBuilder stringBuilder = ReceiveDataUtil.getsData();
        final int size = stringBuilder == null ? 0 : stringBuilder.length() / dataLineLength;
        YzDebug.d("parseAll size:"+size);
        try {
            if (true) {
//                String fileName = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH).format(new Date());
                File file = new File(BtDspApplication.getInstance().getExternalFilesDir("dsp") + "/read_dsp.txt");
                if (file.exists())file.delete();
                YzDebug.d("parseAll file:"+ file.getAbsolutePath());
                FileWriter fileWriter = new FileWriter(file);
                String[] array = stringBuilder.toString().split("55");
                for (int i = 0; i < array.length; i++) {
                    fileWriter.write(array[i] + "\n");
                }
                fileWriter.flush();
                fileWriter.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String indexFmt = "aa%04x",indexStr;
        for (int i = 0; i < size; i++) {
            indexStr = String.format(indexFmt,i);
//            if (i <= 255) {
//                indexStr += "00" + (ByteUtil.intToHexString(i));
//            } else {
//                indexStr += (ByteUtil.intToHexString(i));
//            }
            int index = stringBuilder.indexOf(indexStr);
            if (index != -1) {
                int end = index + dataLineLength;
                if (end >= stringBuilder.length()) {
                    end = stringBuilder.length();
                }
                if (end - index < 10) continue;
                String source = stringBuilder.substring(index, end);
//                BLog.e("parse", indexStr + "=" + source);
                if (TextUtils.isEmpty(source) || source.length() < 6) {
                    continue;
                }
//                String dataStr = source.substring(6, source.length() - 6);
                String dataStr = source.substring(6, source.length() - 2);
                BLog.e("parse", indexStr + " = " + dataStr);
                try {
                    parse(ByteUtil.hexToBytes(dataStr));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                stringBuilder.delete(index, end);
            }
        }
        ReceiveDataUtil.clear();
    }

    public static boolean parseData() {
        StringBuilder data = ReceiveDataUtil.getsData();

        if (data != null && data.length() > 8136) {//此处是超时算得
            int length = data.length();
            if (mPreCheckLength  == length){//数据长度不再增加
                return true;
            }
            mPreCheckLength =length;
            return false;
        }
        return false;
    }


    /**
     * 解析数据
     *
     * @param value
     * @return true 数据可以解析， false 数据无法解析
     */
    public static boolean parse(byte[] value) {
        if (value == null) {
            return false;
        }
        boolean isNull = true;
        for (byte b : value) {
            if (b != NULL && b != 0) {
                isNull = false;
            }
        }
        if (isNull) {
            return true;
        }
        switch (value[0]) {
            case (byte) 0xAA:
                if (value[1] == (byte) 0x83) {
                    BLog.d("parse", "解析summing");
                    parseSummingChannel(value);
                    return true;
                } else {
                    BLog.d("parse", "解析eq");
                    parseEqChannel(value);
                    return true;
                }
            case (byte) 0xAB:
                BLog.d("parse", "解析eq 联调");
                parseEqChannel(value);
                return true;
            case (byte) 0xCC:
                BLog.d("parse", "解析延时");
                //ccc10003000000000000000000ff
                parseDelayChannelForDelay(value);
                return true;
            case (byte) 0xDB:
                BLog.d("parse", "解析音量");
                parseLevelChannel(value);
                return true;
            case (byte) 0xBB:
                BLog.d("parse", "解析相位");
                parseLevelDegree(value);
                return true;
            case (byte) 0xEE:
                BLog.d("parse", "解析总音量");
                parseTotalVolume(value);
                return true;
            case (byte) 0xDD:
                BLog.d("parse", "解析xover 高通");
                parseXover(value, true);
                return true;
            case (byte) 0xDE:
                BLog.d("parse", "解析xover 低通");
                parseXover(value, false);
                return true;
            case (byte) 0x52:
                if (value[1] == (byte) 0x45 && value[2] == (byte) 0x4d) {
                    BLog.d("parse", "解析remote delay");
                    int delay = ByteUtil.get2ByteInt(new byte[]{value[7], value[6]});
                    DspSettings.SUMMING_SETTINGS.setDelay(delay);
                }
                return true;
        }
        return false;
    }

    private static int parseChannel(byte index) {
        return (index & 0x0F) - 1;
    }

    /**
     * 解析eq
     * //发送通道频率、Q值、增益
     * //0xAA~0xAB(前、后声场左右联调), 通道(0xC1~0xC6),点(0x00~0x0E),
     * //频率(0x0014~0x4E20), Q值(0x0005~0x07D0), 增益(0x0000~0x0190)
     *
     * @param value aa c1 030064016900ae00000000ff
     */
    private static void parseEqChannel(byte[] value) {
        int channelCh1 = parseChannel(value[1]);
        if (channelCh1 < 0) return;
        parseEqChannel(channelCh1, value);
    }

    private static void parseEqChannelGrouping(int channel, byte[] value) {
        for (EqChannel eqChannel : DspSettings.EQ_SETTINGS.getEqChannels()) {
            eqChannel.setChannel(value[3]);//点
            eqChannel.getGain()[eqChannel.getChannel()] = value[4] - 0x14;//增益
            eqChannel.getFreq()[eqChannel.getChannel()] = ByteUtil.get2ByteInt(new byte[]{value[6], value[5]});//频率
            eqChannel.getQ()[eqChannel.getChannel()] = ByteUtil.get2ByteInt(new byte[]{value[8], value[7]}) / 10f;//Q值
        }
    }

    private static void parseEqChannel(int channel, byte[] value) {
        EqChannel eqChannel = DspSettings.EQ_SETTINGS.getEqChannels().get(channel);
        int index = value[2];//点
        if (index >= DspSettings.FRENCY_LENGTH || index < 0) return;
        eqChannel.getFreq()[index] = ByteUtil.get2ByteInt(new byte[]{value[4], value[3]});//频率
        eqChannel.getQ()[index] = ByteUtil.get2ByteInt(new byte[]{value[6], value[5]});//Q值
        eqChannel.getGain()[index] = ByteUtil.get2ByteInt(new byte[]{value[8], value[7]}) - SettingConstants.GAIN_OFFSET;//增益

        eqChannel.setFreqVal(Arrays.toString(eqChannel.getFreq()));
        eqChannel.setGainVal(Arrays.toString(eqChannel.getGain()));
        eqChannel.setQVal(Arrays.toString(eqChannel.getQ()));

        BLog.d("parse", "-->eq ch:"+ channel +" index:"+ index);
        BLog.d("parse", "-->eq:"+ eqChannel.getFreqVal());
        BLog.d("parse", "-->eq:"+ eqChannel.getQVal() );
        BLog.d("parse", "-->eq :"+ eqChannel.getGainVal() );

    }

    private static void parseDelayChannelForDelay(byte[] value) {
        int channel = parseChannel(value[1]);
        float val = ByteUtil.get2ByteInt(new byte[]{value[3], value[2]}) / 100f;
        DspSettings.ADVANCE_SETTINGS.setDelayValue(channel, val);
    }

    /**
     * 解析音量
     */
    private static void parseLevelChannel(byte[] value) {
        int channel = parseChannel(value[1]);
        int vol = ByteUtil.get2ByteInt(new byte[]{value[4], value[3]}) / 10;
        LevelChannel levelChannel = DspSettings.ADVANCE_SETTINGS.getChannel().get(channel);
        levelChannel.setChecked(value[2] == (byte) 0x01 ? 1 : 0);
        levelChannel.setMute(value[2]);
        if (vol > Constants.MAX_VOL) vol = Constants.MAX_VOL;
        vol = Constants.MAX_VOL - vol;
        levelChannel.setVal(vol);
    }

    /**
     * 解析相位
     */
    private static void parseLevelDegree(byte[] value) {
        int channel = parseChannel(value[1]);
        LevelChannel levelChannel = DspSettings.ADVANCE_SETTINGS.getChannel().get(channel);
        levelChannel.setDegree(value[2] == (byte) 0x01 ? 1 : 0);
    }

    /**
     * 解析总音量
     */
    private static void parseTotalVolume(byte[] value) {
        //总音量
        DspSettings.ADVANCE_SETTINGS.setMute(value[1] == (byte) 0x01 ? 1 : 0);
        int vol = ByteUtil.get2ByteInt(new byte[]{value[3], value[2]}) / 10;
        if (vol > Constants.MAX_VOL) vol = Constants.MAX_VOL;
        vol = Constants.MAX_VOL - vol;
        DspSettings.ADVANCE_SETTINGS.setTotalVol(vol);
    }

    /**
     * 解析Summing
     */
    private static void parseSummingChannel(byte[] value) {
        int channel = parseChannel(value[3]);
        SummingChannel summingChannel = DspSettings.SUMMING_SETTINGS.getSummingChannels().get(channel);
        int[] input = new int[DspSettings.CHANNEL_LENGTH];
        int start = 4;
        for (int i = 0; i < input.length; i++) {
            input[i] = value[start++];
        }
        summingChannel.setHigh_input_channels(input);
        summingChannel.setHighInputVal(Arrays.toString(summingChannel.getHigh_input_channels()));
    }

    /**
     * 解析分频
     */
    private static void parseXoverGroup(XoverChannel currentChannel, int index) {
        List<XoverChannel> xoverChannels = DspSettings.XOVER_SETTINGS.getXoverChannels();
        for (int i = 0; i < xoverChannels.size(); i++) {
            XoverChannel xoverChannel = xoverChannels.get(i);
            if (xoverChannel.getChannel() != index) {
                xoverChannel.setPassType(currentChannel.getPassType());
                xoverChannel.setLowFilterType(currentChannel.getLowFilterType());
                xoverChannel.setLowFilterValue(currentChannel.getLowFilterValue());
                xoverChannel.setLowFrequency(currentChannel.getLowFrequency());

                xoverChannel.setHighFilterValue(currentChannel.getHighFilterValue());
                xoverChannel.setHighFilterType(currentChannel.getHighFilterType());
                xoverChannel.setHighFrequency(currentChannel.getHighFrequency());
            }
        }
    }

    /**
     * 解析分频
     */
    private static void parseXover(byte[] value, boolean isHigh) {
        int channel = parseChannel(value[1]);
        XoverChannel xoverChannel = DspSettings.XOVER_SETTINGS.getXoverChannels().get(channel);
        int type = isHigh ? 1 : 2;
        int filterType = value[2];
        int filterValue = value[3];
        int freq = ByteUtil.get2ByteInt(new byte[]{value[5], value[4]});
        xoverChannel.setPassType(type);
        if (isHigh) {
            xoverChannel.setHighFilterType(filterType);
            xoverChannel.setHighFilterValue(filterValue);
            xoverChannel.setHighFrequency(freq);
        } else {
            xoverChannel.setLowFilterType(filterType);
            xoverChannel.setLowFilterValue(filterValue);
            xoverChannel.setLowFrequency(freq);
        }
    }
}
